package evm

import (
	"math/big"

	"hundsun.com/hsl/hschain/contract/evm/ext"
	"hundsun.com/hsl/hschain/contract/evm/ext/common"
	"hundsun.com/hsl/hschain/contract/evm/vm"
	"hundsun.com/hsl/hschain/protos"
	"hundsun.com/hsl/hschain/protos/ledger"
)

// NewEVMBlockContext creates a new context for use in the EVM.
func NewEVMBlockContext(msg *ext.Message, header *ledger.BlockHeader) vm.BlockContext {
	addr, _ := protos.ParseAddressFromPublicKeyBytes(header.GetSignature().GetPublicKey())
	return vm.BlockContext{
		CanTransfer: CanTransfer,
		Transfer:    Transfer,
		GetHash:     GetHash,
		Coinbase:    common.HexToAddress(string(addr)), // covert to evm address
		BlockNumber: new(big.Int).SetUint64(header.GetNumber()),
		Time:        new(big.Int).SetInt64(header.GetBlockTime()),
		Difficulty:  new(big.Int).SetUint64(header.GetDifficulty()),
		BaseFee:     new(big.Int).SetUint64(0),
		GasLimit:    msg.GasLimit(),
	}
}

// CanTransfer is the signature of a transfer guard function
func CanTransfer(sdb vm.StateDB, addr common.Address, amount *big.Int) bool {
	return sdb.GetBalance(addr).Cmp(amount) >= 0
}

// Transfer is the signature of a transfer function
func Transfer(sdb vm.StateDB, sender, recipient common.Address, amount *big.Int) {
	sdb.SubBalance(sender, amount)
	sdb.AddBalance(recipient, amount)
}

// GetHash returns the n'th block hash in the blockchain
// and is used by the BLOCKHASH EVM op code.
func GetHash(uint64) common.Hash {
	return common.Hash{}
}

// NewEVMTxContext creates a new transaction context for a single transaction.
func NewEVMTxContext(msg ext.Message) vm.TxContext {
	return vm.TxContext{
		Origin:   msg.From(),
		GasPrice: big.NewInt(int64(msg.GasPrice())),
	}
}
